.long SYMBOL_NAME(do_dom_mem_op)
.long SYMBOL_NAME(do_multicall)
.long SYMBOL_NAME(do_kbd_op)
- .long SYMBOL_NAME(do_set_priv_levels)
.rept NR_syscalls-((.-hypervisor_call_table)/4)
.long SYMBOL_NAME(sys_ni_syscall)
.endr
}
-long do_set_priv_levels(unsigned int new_io_pl, unsigned int new_hypercall_pl)
+/* XXX Currently the 'domain' field is ignored! XXX */
+long do_iopl(unsigned int domain, unsigned int new_io_pl)
{
struct pt_regs *regs = GET_SYSCALL_REGS(current);
-
- /*
- * Any domain can reduce privilege required for hypercall access.
- * Note that access from ring 1 cannot be relinquished.
- */
- current->thread.hypercall_pl = new_hypercall_pl & 3;
-
- /* Only privileged domains can acquire access to I/O ports. */
- if ( IS_PRIV(current) )
- regs->eflags = (regs->eflags & 0xffffcfff) | ((new_io_pl&3) << 12);
-
+ regs->eflags = (regs->eflags & 0xffffcfff) | ((new_io_pl&3) << 12);
return 0;
}
*/
if ( (error_code & 3) == 2 )
{
- /*
- * Hypercalls from rings 2 or 3 fall through to here. If permitted, we
- * will transfer control to the requested hypercall.
- */
- if ( ((error_code>>3) == HYPERVISOR_CALL_VECTOR) &&
- (current->thread.hypercall_pl >= (regs->xcs & 3)) )
- {
- __asm__ __volatile__ (
- "movl %0,%%esp \n"
- "sti \n"
- "andl $255,%%eax \n"
- "call *hypervisor_call_table(,%%eax,4) \n"
- "movl %%eax,0x18(%%esp) \n"
- "jmp ret_from_intr \n"
- : : "r" (regs) );
- }
-
/* This fault must be due to <INT n> instruction. */
ti = current->thread.traps + (error_code>>3);
if ( ti->dpl >= (regs->xcs & 3) )
long ret = 0;
dom0_op_t op;
- if ( current->domain != 0 )
+ if ( !IS_PRIV(current) )
return -EPERM;
if ( copy_from_user(&op, u_dom0_op, sizeof(op)) )
break;
}
+ case DOM0_IOPL:
+ {
+ extern long do_iopl(unsigned int, unsigned int);
+ ret = do_iopl(op.u.iopl.domain, op.u.iopl.iopl);
+ }
+ break;
+
default:
ret = -ENOSYS;
int fast_trap_idx;
struct desc_struct fast_trap_desc;
trap_info_t traps[256];
- int hypercall_pl;
};
#define IDT_ENTRIES 256
#define DOM0_STOPDOMAIN 11
#define DOM0_GETDOMAININFO 12
#define DOM0_BUILDDOMAIN 13
+#define DOM0_IOPL 14
-#define MAX_CMD_LEN 256
-#define MAX_DOMAIN_NAME 16
+#define MAX_CMD_LEN 256
+#define MAX_DOMAIN_NAME 16
typedef struct dom0_newdomain_st
{
typedef struct dom0_bvtctl_st
{
- unsigned long ctx_allow; /* context switch allowance */
+ unsigned long ctx_allow; /* context switch allowance */
} dom0_bvtctl_t;
typedef struct dom0_adjustdom_st
{
unsigned int domain; /* domain id */
- unsigned long mcu_adv; /* mcu advance: inverse of weight */
- unsigned long warp; /* time warp */
- unsigned long warpl; /* warp limit */
- unsigned long warpu; /* unwarp time requirement */
+ unsigned long mcu_adv; /* mcu advance: inverse of weight */
+ unsigned long warp; /* time warp */
+ unsigned long warpl; /* warp limit */
+ unsigned long warpu; /* unwarp time requirement */
} dom0_adjustdom_t;
typedef struct dom0_getdominfo_st
{
- unsigned int domain; /* All returns except domain */
- char name[MAX_DOMAIN_NAME];
- int processor;
- int has_cpu;
- int state;
- int hyp_events;
- unsigned long mcu_advance;
- unsigned long pg_head;
- unsigned int tot_pages;
- long long cpu_time;
+ unsigned int domain; /* All returns except domain */
+ char name[MAX_DOMAIN_NAME];
+ int processor;
+ int has_cpu;
+ int state;
+ int hyp_events;
+ unsigned long mcu_advance;
+ unsigned long pg_head;
+ unsigned int tot_pages;
+ long long cpu_time;
} dom0_getdominfo_t;
+typedef struct dom0_iopl_st
+{
+ unsigned int domain;
+ unsigned int iopl;
+} dom0_iopl_t;
+
#ifndef NO_DOM0_OP_T
typedef struct dom0_op_st
{
dom0_newdomain_t newdomain;
dom0_killdomain_t killdomain;
dom0_getmemlist_t getmemlist;
- dom0_bvtctl_t bvtctl;
- dom0_adjustdom_t adjustdom;
+ dom0_bvtctl_t bvtctl;
+ dom0_adjustdom_t adjustdom;
dom_meminfo_t meminfo;
dom0_getdominfo_t getdominfo;
- }
+ dom0_iopl_t iopl;
+ }
u;
} dom0_op_t;
#endif
#define __HYPERVISOR_dom_mem_op 17
#define __HYPERVISOR_multicall 18
#define __HYPERVISOR_kbd_op 19
-#define __HYPERVISOR_set_priv_levels 20
/* And the trap vector is... */
#define TRAP_INSTR "int $0x82"
copy_from_user(&op, buffer, sizeof(dom0_op_t));
- /* do some sanity checks */
- if(op.cmd > MAX_CMD){
- ret = -ENOSYS;
- goto out;
- }
-
if ( op.cmd == MAP_DOM_MEM )
{
ret = dom_map_mem(op.u.dommem.domain, op.u.dommem.start_pfn,
#endif
/* Extra commands dealt with by Xenolinux. */
-#define MAP_DOM_MEM 14
-#define DO_PGUPDATES 15
-#define MAX_CMD 16
+#define MAP_DOM_MEM 1014
+#define DO_PGUPDATES 1015
typedef struct dom_mem
{
dom_pgupdate_t pgupdate;
dom_meminfo_t meminfo;
dom0_getdominfo_t getdominfo;
- }
- u;
+ dom0_iopl_t iopl;
+ } u;
} dom0_op_t;
#endif /* __DOM0_DOM0_OPS_H__ */
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/stddef.h>
+#include <asm/hypervisor-ifs/dom0_ops.h>
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
asmlinkage int sys_iopl(unsigned long unused)
{
struct pt_regs *regs = (struct pt_regs *)&unused;
- unsigned int new_io_pl = regs->ebx & 3;
+ unsigned int new_io_pl = regs->ebx;
unsigned int old_io_pl = current->thread.io_pl;
- unsigned int new_hypercall_pl = (regs->ebx >> 2) & 3;
- unsigned int old_hypercall_pl = current->thread.hypercall_pl;
+ dom0_op_t op;
- /* Need "raw I/O" privileges for direct port access. */
- if ( (new_io_pl > old_io_pl) &&
- (!capable(CAP_SYS_RAWIO) || !(start_info.flags & SIF_PRIVILEGED)) )
+ if ( !(start_info.flags & SIF_PRIVILEGED) )
return -EPERM;
- /* Just need generic root/admin privileges for direct hypercall access. */
- if ( (new_hypercall_pl > old_hypercall_pl) && !capable(CAP_SYS_ADMIN) )
+ if ( new_io_pl > 3 )
+ return -EINVAL;
+
+ /* Need "raw I/O" privileges for direct port access. */
+ if ( (new_io_pl > old_io_pl) && !capable(CAP_SYS_RAWIO) )
return -EPERM;
/* Maintain OS privileges even if user attempts to relinquish them. */
- if ( new_hypercall_pl == 0 )
- new_hypercall_pl = 1;
if ( (new_io_pl == 0) && (start_info.flags & SIF_PRIVILEGED) )
new_io_pl = 1;
/* Change our version of the privilege levels. */
- current->thread.io_pl = new_io_pl;
- current->thread.hypercall_pl = new_hypercall_pl;
+ current->thread.io_pl = new_io_pl;
/* Force the change at ring 0. */
- HYPERVISOR_set_priv_levels(new_io_pl, new_hypercall_pl);
+ op.cmd = DOM0_IOPL;
+ op.u.iopl.domain = start_info.dom_id;
+ op.u.iopl.iopl = new_io_pl;
+ HYPERVISOR_dom0_op(&op);
return 0;
}
#include <asm/desc.h>
#include <asm/mmu_context.h>
#include <asm/multicall.h>
+#include <asm/hypervisor-ifs/dom0_ops.h>
#include <linux/irq.h>
__asm__ __volatile__ ( "pushfl; popl %0" : "=r" (eflags) : );
p->thread.io_pl = (eflags >> 12) & 3;
- /* We're careful with hypercall privileges. Don't allow inheritance. */
- p->thread.hypercall_pl = 1;
-
return 0;
}
}
queue_multicall2(__HYPERVISOR_stack_switch, __KERNEL_DS, next->esp0);
- /* Next call will silently fail if we are a non-privileged guest OS. */
- queue_multicall2(__HYPERVISOR_set_priv_levels,
- next->io_pl, next->hypercall_pl);
+ if ( start_info.flags & SIF_PRIVILEGED )
+ {
+ dom0_op_t op;
+ op.cmd = DOM0_IOPL;
+ op.u.iopl.domain = start_info.dom_id;
+ op.u.iopl.iopl = next->io_pl;
+ queue_multicall1(__HYPERVISOR_dom0_op, (unsigned long)&op);
+ }
/* EXECUTE ALL TASK SWITCH XEN SYSCALLS AT THIS POINT. */
execute_multicall_list();
#include <asm/mpspec.h>
#include <asm/mmu_context.h>
#include <asm/hypervisor.h>
+#include <asm/hypervisor-ifs/dom0_ops.h>
shared_info_t *HYPERVISOR_shared_info;
paging_init();
- current->thread.hypercall_pl = 1;
- if ( start_info.flags & SIF_PRIVILEGED ) {
- current->thread.io_pl = 1;
- /* We are privileged guest os - should have IO privileges. */
- if( HYPERVISOR_set_priv_levels(1, 1) )
+ /* We are privileged guest os - should have IO privileges. */
+ if ( start_info.flags & SIF_PRIVILEGED )
+ {
+ dom0_op_t op;
+ op.cmd = DOM0_IOPL;
+ op.u.iopl.domain = start_info.dom_id;
+ op.u.iopl.iopl = 1;
+ if( HYPERVISOR_dom0_op(&op) != 0 )
panic("Unable to obtain IOPL, despite being SIF_PRIVILEGED");
+ current->thread.io_pl = 1;
}
if(start_info.flags & SIF_CONSOLE)
return ret;
}
-static inline long HYPERVISOR_set_priv_levels(unsigned int new_io_pl,
- unsigned int new_hypercall_pl)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_set_priv_levels),
- "b" (new_io_pl), "c" (new_hypercall_pl) );
-
- return ret;
-}
-
#endif /* __HYPERVISOR_H__ */
unsigned long esp;
unsigned long fs;
unsigned long gs;
- unsigned int io_pl, hypercall_pl;
+ unsigned int io_pl;
/* Hardware debugging registers */
unsigned long debugreg[8]; /* %%db0-7 debug registers */
/* fault info */